package com.bstek.ureport.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

public class DateUtils {

	// 验证日期格式为yyyy-MM-DD的正则表达式为
	private static final String datePattern = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)";

	// 验证日期格式为yyyy-MM-dd HH:mm:ss的正则表达式为
	private static final String datetimePattern = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";

	public static Date toDate(Object obj) {
		if (obj == null || StringUtils.isBlank(obj.toString())) {
			return null;
		}
		if (obj instanceof Date) {
			return (Date) obj;
		}
		if (obj instanceof LocalDate) {
			LocalDate localDate = (LocalDate) obj;
			return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
		}
		if (obj instanceof LocalDateTime) {
			LocalDateTime localDateTime = (LocalDateTime) obj;
			return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
		}
		if (obj instanceof String) {
			return parseDate(String.valueOf(obj));
		}
		return null;
	}

	public static LocalDateTime toLocalDateTime(Object obj) {
		if (obj == null) {
			return null;
		}
		if (obj instanceof Date) {
			Date date = (Date) obj;
			return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
		}
		if (obj instanceof LocalDate) {
			LocalDate localDate = (LocalDate) obj;
			return localDate.atStartOfDay();
		}
		if (obj instanceof LocalDateTime) {
			return (LocalDateTime) obj;
		}
		return parseLocalDateTime(String.valueOf(obj));
	}

	public static String format(Object data, String format) {
		if (data instanceof Date) {
			Date d = (Date) data;
			LocalDateTime localDateTime = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
			DateTimeFormatter dt = DateTimeFormatter.ofPattern(format);
			return dt.format(localDateTime);
		}
		if (data instanceof LocalDateTime) {
			LocalDateTime d = (LocalDateTime) data;
			DateTimeFormatter dt = DateTimeFormatter.ofPattern(format);
			return dt.format(d);
		}
		if (data instanceof LocalDate) {
			LocalDate d = (LocalDate) data;
			DateTimeFormatter dt = DateTimeFormatter.ofPattern(format);
			return dt.format(d);
		}
		return null;
	}

	public static boolean isDate(Object object) {
		if (object instanceof Date) {
			return true;
		}
		if (object instanceof LocalDate) {
			return true;
		}
		if (object instanceof LocalDateTime) {
			return true;
		}
		return false;
	}

	private static Date parseDate(String value) {
		if (value.matches(datePattern)) {
			LocalDate localDate = LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
			return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
		}
		if (value.matches(datetimePattern)) {
			LocalDateTime localDateTime = LocalDateTime.parse(value,
					DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
			return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
		}
		return null;
	}

	private static LocalDateTime parseLocalDateTime(String value) {
		if (value.matches(datePattern)) {
			LocalDate localDate = LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
			return localDate.atStartOfDay();
		}
		if (value.matches(datetimePattern)) {
			LocalDateTime localDateTime = LocalDateTime.parse(value,
					DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
			return localDateTime;
		}
		return null;
	}
}
